package com.mars.web.rest.controller;

import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.mars.base.common.utils.CommonUtils;
import com.mars.base.common.utils.CookieUtils;
import com.mars.base.common.utils.RandomUitl;
import com.mars.base.common.utils.security.PasswordUtils;
import com.mars.base.web.BaseController;
import com.mars.base.web.utils.ResponseResult;
import com.mars.component.redis.JedisClient;
import com.mars.manager.user.entity.User;
import com.mars.manager.user.service.UserService;

@RestController
@RequestMapping(value="/sso")
public class SSOController extends BaseController{

	@Autowired
	private UserService userService ;
	
	@Autowired
	private JedisClient jedisClient ;
	
	/**
	 * Redis中的Session Key
	 */
	@Value("${SSO_REDIS_SESSION_KEY}")
	private String sesisonKey ;
	
	/**
	 * Redis Session的过期时间
	 */
	@Value("${SSO_REDIS_SESSION_EXPIRE}")
	private Integer sessionExpire ;
	
	/**
	 * Redis记录登陆错误次数的KEY
	 */
	@Value("${SSO_REDIS_PWD_ERROR_COUNT}")
	private String pwdErrorCount ;
	
	/**
	 * 登陆验证错误达到指定次数，需要输入验证码
	 */
	@Value("${SSO_SHOW_VALIDATE_COUNT}")
	private String showValidCount ;
	
	/**
	 * 登陆验证错误到达指定次数将锁定账号
	 */
	@Value("${SSO_LOCK_ACCOUNT_COUNT}")
	private String lockAccountCount ;
	
	/**
	 * 账号锁定时间
	 */
	@Value("${SSO_LOCK_TIME}")
	private String lockTime ;
	
	/**
	 * Cookie中的Token Key
	 */
	@Value("${SSO_COOKIE_TOKEN}")
	private String cookieKey ;
	
	/**
	 * 登陆验证
	 * @param username 账号
	 * @param password 密码
	 * @param validate 验证码
	 * @param isValid  是否打开验证码（false: 不打开, true: 打开）
	 * @param isLock   登陆失败达到指定次数，是否允许锁定账号（false: 不锁定, true: 锁定），锁定时间：默认30分钟
	 * @return
	 */
	@ApiOperation(value="SSO单点验证服务",  notes="", response=ResponseResult.class)
	@ApiImplicitParams({
		@ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "String"),
		@ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String"),
		@ApiImplicitParam(name = "validate", value = "验证码", required = false, dataType = "String"),
		@ApiImplicitParam(name = "isValid", value = "是否实现验证码", required = false, dataType = "String"),
		@ApiImplicitParam(name = "isLock", value = "是否允许锁定", required = false, dataType = "String")
	})
	@PostMapping(value = "/login")
	public Object login(String username, String password, String validate, boolean isValid, boolean isLock) {
		System.out.println("账号》"+username);
		System.out.println("密码》"+password);
		Map<String, Object> msg = new HashMap<String, Object>() ;
		
		if(CommonUtils.isEmpty(username) && CommonUtils.isEmpty(password)) {
			return ResponseResult.build(false, "请填写账号和密码", msg) ;
		}
		if(CommonUtils.isEmpty(username)) {
			return ResponseResult.build(false, "请填写账号", msg) ;
		}
		if(CommonUtils.isEmpty(password)) {
			return ResponseResult.build(false, "请填写密码", msg) ;
		}
		//打开验证码时
		if(isValid) {
			//当需要填写验证码时判断
			if(CommonUtils.isEmpty(username) && CommonUtils.isEmpty(password) && CommonUtils.isEmpty(validate)) {
				return ResponseResult.build(false, "请填写账号和密码及验证码", msg) ;
			}
			if(CommonUtils.isEmpty(validate)) {
				return ResponseResult.build(false, "请填写验证码", msg) ;
			}
		}
		
		//登陆密码错误次数Key
		String pwdErrorCountKey = this.pwdErrorCount + username + ":" + request.getSession().getId() ;
		//取得登陆错误次数
		String loginErrorCount = this.jedisClient.get(pwdErrorCountKey) ;
		//取得账号锁定时间
		Long lockTimeTTL = this.jedisClient.ttl(pwdErrorCountKey) ;
		
		//判断是否允许锁定
		if(isLock) {
			// 错误次数达到指定次数将锁定，默认错误次数6次
			if(null != loginErrorCount && Integer.parseInt(loginErrorCount) == Integer.parseInt(this.lockAccountCount)) {
				//设置锁定时间
				this.jedisClient.expire(pwdErrorCountKey, Integer.parseInt(this.lockTime)) ;
				
				msg.put("lock", true) ;
				msg.put("loginErrorCount", loginErrorCount) ;
				return ResponseResult.build(false, "登陆失败，账号已被锁定，"+(lockTimeTTL/1000)+"分钟后解锁", msg) ;
			} else {
				if(null != lockTimeTTL && lockTimeTTL > 0) {
					return ResponseResult.build(false, "登陆错误次数过多，账号已被锁定，"+(lockTimeTTL/1000)+"分钟后解锁", msg) ;
				}
			}
		}
		
		
		User user = this.userService.gerUserByUserName(username) ;
		if(null == user) {
			//打开验证码时
			if(isValid) {
				// 达到指定次数，显示验证码
				if(null != loginErrorCount && Integer.parseInt(loginErrorCount) > Integer.parseInt(this.showValidCount)) {
					msg.put("valid", true) ;
					msg.put("loginErrorCount", loginErrorCount) ;
				}
			}
			return ResponseResult.build(false, "登陆失败，账号或密码错误", msg) ;
		} else {
			//判断账号状态
			if(!user.getStatus()) {
				return ResponseResult.build(false, "账号已被禁用，请联系管理员", msg) ;
			}
			
			//密码错误
			if(!PasswordUtils.isPasswordValid(user.getPassword(), username, password, user.getSalt())) {
				//记录验证错误次数保存到Redis缓存中
				this.jedisClient.incr(pwdErrorCountKey);
				
				return ResponseResult.build(false, "登陆失败，账号或密码错误", msg) ;
			}
			
			
			//登陆验证通过，清除验证码显示和锁定缓存信息
			this.jedisClient.del(pwdErrorCountKey) ;
			
			//生成用户会话Token
			String token = RandomUitl.uuid() ;
			//密码设置未NULL
			user.setPassword(null);
			
			//设置用户会话Token到Cookie中并设定过期时间
			CookieUtils.setCookie(this.request, this.response, this.cookieKey, token);
			
			Cookie cook=new Cookie("userName","lisi");
	        cook.setPath("/");
	        cook.setMaxAge(-1);
	        cook.setDomain(".mars.com");
	        response.addCookie(cook);
			
			
			//保存用户会话Token到Redis缓存中并设定过期时间
			this.jedisClient.setHash(this.sesisonKey, user.getUsername(), JSON.toJSONString(user));
			this.jedisClient.expire(this.sesisonKey, this.sessionExpire) ;
			
			//返回成功信息
			return ResponseResult.build(true, "登陆成功", msg) ;
		}
	}

	
	
}
